<template name="my-sign">
	<view class="signature-wrap" :style="$s.view_color">
		<view v-show="show" class="signature-contain">
			<view class="signature-main">
				<view class="signature-title"><text v-for="(t,index) in titles" :key="index">{{t}}</text></view>
				<canvas
					:canvas-id="cid"
					:id="cid"
					disable-scroll="true"
					class="signature"
					@touchstart="onTouchStart"
					@touchmove="onTouchMove"
					@touchend="onTouchEnd"
				></canvas>
				
				<view class="signature-btns">
					<view class="btn btn-cancel cu-btn bg-main margin-tb-sm text-white" @click="revoke()">
						<text>撤</text><text>销</text>
					</view>
					<view class="btn btn-clear cu-btn bg-main margin-tb-sm text-white" @click="clear();">
						<text>清</text><text>空</text>
					</view>
					<view class="btn btn-ok cu-btn bg-main margin-tb-sm text-white" @click="saveImage()">
						<text>确</text><text>定</text>
					</view>
				</view>
			</view>
		</view>
	</view>
</template>

<script>
/**
 * sign canvas 手写签名
 * @description 设置线条宽度、颜色，撤回，清空
 * @tutorial
 * @property {String} cid canvas id 不设置则默认为 v-sign-时间戳
 * @property {String, Number} width canvas 宽度
 * @property {String, Number} height canvas 高度
 * @property {Object} customStyle canvas 自定义样式
 * @property {String} lineWidth 画笔大小，权重小于 v-sign-pen 组件设置的画笔大小
 * @property {Number} lineColor 画笔颜色，权重小于 v-sign-pen 组件设置的画笔大小
 * @event {Function} init 当创建完 canvas 实例后触发，向外提供 canvas实例，撤回，清空方法
 * @example <v-sign @init="signInit"></v-sign>
 */
import { formatSize } from '@/uni_modules/v-sign/utils'

export default {
	name: 'my-sign',
	props: {
		// canvas id
		cid: {
			type: String,
			default: `v-sign-${Date.now()}`
			// required: true
		},
		// canvas 宽度
		width: {
			type: [String, Number],
			default: '100%'
		},
		// canvas 高度
		height: {
			type: [String, Number],
			default: 300
		},
		// 画笔大小，权重小于 v-sign-pen 组件设置的画笔大小 penLineWidth
		lineWidth: {
			type: Number,
			default: 4
		},
		// 线颜色，权重小于 v-sign-color 组件设置的画笔颜色 penLineColor
		lineColor: {
			type: String,
			default: '#333'
		},
		// canvas自定义样式
		customStyle: {
			type: Object,
			default: () => ({})
		},
		//弹出框
		show: {
			type: Boolean,
			default: true,
		},
		
		title: {
			type: String,
			default: '请签字',
		},
	},
	provide() {
		return {
			getSignInterface: this.provideSignInterface
		}
	},
	data() {
		return {
			formatSize,
			lineData: [],
			winWidth: 0,
			winHeight: 0,
			penLineWidth: null, // v-sign-pen 组件设置的画笔大小
			penLineColor: null ,// v-sign-color 组件设置的颜色
			imageData:"",
			isWrite:false,
		}
	},
	computed:{
		titles() {
			return this.title.split('')
		},
	},
	mounted() {
		this.canvasCtx = uni.createCanvasContext(this.cid, this)
		// 获取窗口宽高
		uni.getSystemInfo({
			success: res => {
				this.winWidth = res.windowWidth
				this.winHeight = res.windowHeight
			}
		})
	},
	methods: {
		onTouchStart(e) {
			this.isWrite=true
			const pos = e.touches[0]
			this.lineData.push({
				style: {
					color: this.penLineColor || this.lineColor,
					width: this.penLineWidth || this.lineWidth
				},
				// 屏幕坐标
				coordinates: [
					{
						type: e.type,
						x: pos.x,
						y: pos.y
					}
				]
			})
			this.drawLine()
		},
		onTouchMove(e) {
			this.isWrite=true
			const pos = e.touches[0]
			this.lineData[this.lineData.length - 1].coordinates.push({
				type: e.type,
				x: pos.x,
				y: pos.y
			})
			this.drawLine()
		},
		onTouchEnd(e) {
			// console.log(e.type, e)
		},
		// 清空画布
		clear() {
			this.isWrite=false
			this.lineData = []
			this.canvasCtx.clearRect(0, 0, this.winWidth, this.winHeight)
			this.canvasCtx.draw()
		},
		// 撤销
		revoke() {
			this.lineData.pop()
			this.lineData.forEach((item, index) => {
				this.canvasCtx.beginPath()
				this.canvasCtx.setLineCap('round')
				this.canvasCtx.setStrokeStyle(item.style.color)
				this.canvasCtx.setLineWidth(item.style.width)
				if (item.coordinates.length < 2) {
					const pos = item.coordinates[0]
					this.canvasCtx.moveTo(pos.x, pos.y)
					this.canvasCtx.lineTo(pos.x + 1, pos.y)
				} else {
					item.coordinates.forEach(pos => {
						if (pos.type == 'touchstart') {
							this.canvasCtx.moveTo(pos.x, pos.y)
						} else {
							this.canvasCtx.lineTo(pos.x, pos.y)
						}
					})
				}
				this.canvasCtx.stroke()
			})
			this.canvasCtx.draw()
		},
		// 绘制线条
		drawLine() {
			const lineDataLen = this.lineData.length
			if (!lineDataLen) return
			const currentLineData = this.lineData[lineDataLen - 1]
			const coordinates = currentLineData.coordinates
			const coordinatesLen = coordinates.length
			if (!coordinatesLen) return
			let startPos
			let endPos
			if (coordinatesLen < 2) {
				// only start, no move event
				startPos = coordinates[coordinatesLen - 1]
				endPos = { x: startPos.x + 1, y: startPos.y }
			} else {
				startPos = coordinates[coordinatesLen - 2]
				endPos = coordinates[coordinatesLen - 1]
			}

			const style = currentLineData.style
			this.canvasCtx.beginPath()
			this.canvasCtx.setLineCap('round')
			this.canvasCtx.setStrokeStyle(style.color)
			this.canvasCtx.setLineWidth(style.width)
			this.canvasCtx.moveTo(startPos.x, startPos.y)
			this.canvasCtx.lineTo(endPos.x, endPos.y)
			// const P1 = this.caculateBezier(startPos, endPos, centerPos)
			// console.log(P1.x, P1.y)
			// this.canvasCtx.moveTo(startPos.x, startPos.y)
			// this.canvasCtx.quadraticCurveTo(P1.x, P1.y, endPos.x, endPos.y)
			this.canvasCtx.stroke()
			this.canvasCtx.draw(true)
		},
		// 保存png图片，文件名配置 filename 仅支持 h5
		async saveImage(filename = '签名') {
			if(!this.isWrite){
				uni.showToast({title:'请先签名',icon:'none'});
				return false
			}
			const tempFilePath = await this.canvasToTempFilePath()
			return new Promise((resolve, reject) => {
				// #ifdef H5
				try {
					const a = document.createElement('a')
					a.href = tempFilePath
					a.download = filename
					document.body.appendChild(a)
					a.click()
					a.remove()
					resolve({ errMsg: 'saveImageH5:ok' })
				} catch (e) {
					console.error(e)
					reject(e)
				}
				// #endif
				// #ifndef H5
				let self=this
				uni.canvasToTempFilePath({
					canvasId: this.cid,
					fileType: 'png',
					quality: 1, //图片质量
					success:function(res) {
						let path=res.tempFilePath	
						self.$emit('confirm',path)
					},
					fail(e){
						console.log(e)
					}
				},this)		
				// #endif
			})
		},
		
		// canvas 保存为临时图片路径，h5 为base64
		canvasToTempFilePath(conf = {}) {
			return new Promise((resolve, reject) => {
				uni.canvasToTempFilePath(
					{
						canvasId: this.cid,
						...conf,
						success: res => {
							resolve(res.tempFilePath)
						},
						fail: err => {
							console.log('fail', err)
							reject(err)
						}
					},
					this
				)
			})
		},
		setLineWidth(numberVal) {
			this.penLineWidth = numberVal
		},
		setLineColor(strValue) {
			this.penLineColor = strValue
		},
		/**
		 * 计算二次贝塞尔曲线 控制点 P1
		 * 起点 P0(x0,y0)、控制点P1(x1, y1)、P2(x2, y2)、曲线上任意点B(x, y)
		 * 二次贝塞尔公式：B(t) = (1-t)²P0 + 2t(1-t)P1 + t²P2
		 * 代入坐标得：
		 * x = (1-t)²*x0 + 2t(1-t)*x1 + t²*x2
		 * y = (1-t)²*y0 + 2t(1-t)*y1 + t²*y2
		 */
		caculateBezier(P0, P2, B, t = 0.5) {
			const { x: x0, y: y0 } = P0
			const { x: x2, y: y2 } = P2
			const { x, y } = B
			let x1 = (x - (1 - t) * (1 - t) * x0 - t * t * x2) / (2 * t * (1 - t))
			let y1 = (y - (1 - t) * (1 - t) * y0 - t * t * y2) / (2 * t * (1 - t))
			return { x: x1, y: y1 }
		}
	}
}
</script>

<style lang="scss" scoped>
	.signature-wrap {
		height: 100%;
		width: 100%;
		position: relative;
		// padding: 0 5px;
	}

	.signature-contain {
		position:absolute;
		left: 0;
		top: 0;
		width: 100%;
		height:calc(100vh - 100px);
		overflow: hidden;

		.signature-main {
			background: white;
			flex-direction: row-reverse;
			display: flex;
			align-items: stretch;
			height: 100%;
		}

		.signature-title {
			font-weight: bold;
			font-size: 36rpx;
			display: flex;
			// padding: 0 20rpx;
			flex-direction: column;
			justify-content: center;
			color: $uni-text-color;
			width: 15vw;
			text {
				transform: rotate(90deg);
			}
		}

		.signature {
			border: 1px dotted black;
			border-bottom: 1px dotted black;
			background: #FFF;
			margin: 10px 0;
			width: 70vw;
			height: 84vh;
			align-self: center;
			// pointer-events:none;
		}

		.signature-btns {
			display: flex;
			padding: 2px;
			// margin-right: 5px;
			flex-direction: column;
			width: 15vw;

			.btn {
				flex-grow: 1;
				flex-shrink: 0;
				padding: 20rpx;
				font-size: 36rpx;
				margin: 0;
				text-align: center;
				text-decoration: none;
				height: 30vh;
				display: flex;
				align-content: center;
				justify-content: center;
				flex-direction: column;

				text {
					transform: rotate(90deg);
				}

				&+.btn {
					border-top: 1px solid #eee;
				}

				&.btn-clear {
					// background-color: #fc2a07;
					color: $uni-color-success;
				}

				&.btn-cancel {
					// background-color: #eff4f4;
					color: $uni-color-warning;
				}

				&.btn-ok {
					// background-color: $uni-color-success;
					color: $uni-color-primary;
				}
			}
		}
	}
</style>
